package com.ruoyi.merchant.service.impl;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.merchant.domain.Merchant;
import com.ruoyi.merchant.domain.dto.UpdateMerchantInfoRequest;
import com.ruoyi.merchant.domain.dto.UpdateShopInfoDTO;
import com.ruoyi.merchant.domain.vo.MerchantDetailVO;
import com.ruoyi.merchant.domain.vo.ShopStatusVO;
import com.ruoyi.merchant.domain.vo.UpdateStatusResponse;
import com.ruoyi.merchant.mapper.MerchantMapper;
import com.ruoyi.merchant.service.IMerchantService;
import com.ruoyi.merchant.utils.MerchantSecurityUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class MerchantServiceImpl implements IMerchantService {

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private TokenService tokenService; // RuoYi 通用的登录态管理（如你的项目命名不同请替换）

    private static final String SMS_CODE_KEY = "sms_code:"; // 与登录保持一致

    /**
     * 营业状态映射
     */
    private static final Map<Integer, String> STATUS_MAP = new HashMap<>();

    static {
        STATUS_MAP.put(0, "营业中");
        STATUS_MAP.put(1, "休息中");
        STATUS_MAP.put(2, "已封禁");
    }

    @Override
    public int updateAutoAcceptSetting(Integer autoAcceptOrder, Integer autoAcceptTime) {
        Long merchantId = MerchantSecurityUtils.getMerchantId();

        // 验证参数
        if (autoAcceptOrder == null || (autoAcceptOrder != 0 && autoAcceptOrder != 1)) {
            throw new ServiceException("自动接单参数错误");
        }

        if (autoAcceptOrder == 1) {
            if (autoAcceptTime == null || autoAcceptTime < 5 || autoAcceptTime > 120) {
                throw new ServiceException("预计完成时间必须在5-120分钟之间");
            }
        }

        return merchantMapper.updateAutoAcceptSetting(merchantId, autoAcceptOrder, autoAcceptTime);
    }

    @Override
    public Merchant getAutoAcceptSetting() {
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        return merchantMapper.selectMerchantById(merchantId);
    }



    /**
     * 更新门店信息
     *
     * @param updateDTO 更新信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateShopInfo(UpdateShopInfoDTO updateDTO) {
        // 从token中获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }

        // 根据商家ID查询商家信息
        Merchant merchant = merchantMapper.selectMerchantById(merchantId);
        if (merchant == null) {
            throw new ServiceException("商家信息不存在");
        }

        // 检查商家状态
        if (merchant.getStatus() == 2) {
            throw new ServiceException("商家已被封禁，无法修改信息");
        }

        // 验证营业执照和食品许可证是否重复（如果有修改）
        if (StringUtils.isNotEmpty(updateDTO.getBusinessLicense())
                && !updateDTO.getBusinessLicense().equals(merchant.getBusinessLicense())) {
            checkBusinessLicenseDuplicate(updateDTO.getBusinessLicense(), merchantId);
        }

        if (StringUtils.isNotEmpty(updateDTO.getFoodLicense())
                && !updateDTO.getFoodLicense().equals(merchant.getFoodLicense())) {
            checkFoodLicenseDuplicate(updateDTO.getFoodLicense(), merchantId);
        }

        // 更新商家信息
        Merchant updateMerchant = new Merchant();
        updateMerchant.setMerchantId(merchantId);
        BeanUtils.copyProperties(updateDTO, updateMerchant);

        return merchantMapper.updateMerchantInfo(updateMerchant);
    }

    /**
     * 检查营业执照是否重复
     *
     * @param businessLicense 营业执照号
     * @param merchantId 当前商家ID
     */
    private void checkBusinessLicenseDuplicate(String businessLicense, Long merchantId) {
        int count = merchantMapper.checkBusinessLicenseDuplicate(businessLicense, merchantId);
        if (count > 0) {
            throw new ServiceException("营业执照号已被其他商家使用");
        }
    }

    /**
     * 检查食品经营许可证是否重复
     *
     * @param foodLicense 食品经营许可证号
     * @param merchantId 当前商家ID
     */
    private void checkFoodLicenseDuplicate(String foodLicense, Long merchantId) {
        int count = merchantMapper.checkFoodLicenseDuplicate(foodLicense, merchantId);
        if (count > 0) {
            throw new ServiceException("食品经营许可证号已被其他商家使用");
        }
    }

    /**
     * 查询门店营业状态
     *
     * @return 门店状态信息
     */
    @Override
    public ShopStatusVO getShopStatus() {
        // 从token中获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }

        // 根据商家ID查询商家信息
        Merchant merchant = merchantMapper.selectMerchantById(merchantId);
        if (merchant == null) {
            throw new ServiceException("商家信息不存在");
        }

        // 构建返回结果
        ShopStatusVO statusVO = new ShopStatusVO();
        statusVO.setMerchantId(merchant.getMerchantId());
        statusVO.setStatus(merchant.getStatus());
        statusVO.setStatusName(STATUS_MAP.getOrDefault(merchant.getStatus(), "未知状态"));
        statusVO.setRating(merchant.getRating());
        statusVO.setUpdateTime(merchant.getUpdatedAt());

        return statusVO;
    }

    /**
     * 获取商家详情信息
     * @param merchantId 商家ID
     * @return
     */
    @Override
    public MerchantDetailVO getMerchantInfo(Long merchantId) {
        // 1. 查询商家信息
        Merchant merchant = merchantMapper.selectMerchantById(merchantId);
        if (merchant == null) {
            throw new ServiceException("商家信息不存在");
        }

        // 2. 获取审核状态
        String auditStatus = StringUtils.defaultIfBlank(
            merchant.getExternField1(), "PENDING_INFO");

        // 3. 判断信息是否完善
        boolean isInfoComplete = isInfoComplete(merchant);

        // 4. 判断是否可以营业
        boolean canOperate = canOperate(merchant, auditStatus);

        // 5. 获取状态文本
        String statusText = getStatusText(merchant.getStatus());
        String auditStatusText = getAuditStatusText(auditStatus);

        // 6. 获取拒绝原因（如果有）
        String rejectReason = null;
        if ("REJECTED".equals(auditStatus)) {
            // 从extern_field2中读取拒绝原因（如果存储了的话）
            rejectReason = merchant.getExternField2();
        }

        // 7. 构建返回对象
        return MerchantDetailVO.builder()
                .merchantId(merchant.getMerchantId())
                .userId(merchant.getUserId())
                .merchantName(merchant.getMerchantName())
                .contactPerson(merchant.getContactPerson())
                .contactPhone(desensitizePhone(merchant.getContactPhone()))
                .fullContactPhone(merchant.getContactPhone())  // 如果需要完整电话
                .avatarUrl(merchant.getAvatarUrl())
                .address(merchant.getAddress())
                .latitude(merchant.getLatitude())
                .longitude(merchant.getLongitude())
                .businessLicense(merchant.getBusinessLicense())
                .businessLicenseImage(getImageUrl(merchant, "businessLicense"))
                .foodLicense(merchant.getFoodLicense())
                .foodLicenseImage(getImageUrl(merchant, "foodLicense"))
                .status(merchant.getStatus())
                .statusText(statusText)
                .auditStatus(auditStatus)
                .auditStatusText(auditStatusText)
                .rejectReason(rejectReason)
                .rating(merchant.getRating())
                .isInfoComplete(isInfoComplete)
                .canOperate(canOperate)
                .createdAt(merchant.getCreatedAt())
                .updatedAt(merchant.getUpdatedAt())
                .build();
    }

    /**
     * 上传商家头像
     * @param merchantId
     * @param avatarUrl
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAvatar(Long merchantId, String avatarUrl) {
        // 1. 查询商家是否存在
        Merchant merchant = merchantMapper.selectMerchantById(merchantId);
        if (merchant == null) {
            throw new ServiceException("商家信息不存在");
        }

        // 2. 更新头像
        Merchant updateMerchant = new Merchant();
        updateMerchant.setMerchantId(merchantId);
        updateMerchant.setAvatarUrl(avatarUrl);

        int rows = merchantMapper.updateMerchant(updateMerchant);
        if (rows <= 0) {
            throw new ServiceException("更新头像失败");
        }
    }

    /**
     * 修改商家个人信息
     * @param merchantId 商家ID
     * @param request 修改请求
     */
    @Override
    public void updateMerchantInfo(Long merchantId, UpdateMerchantInfoRequest request) {
        Merchant merchant = merchantMapper.selectMerchantById(merchantId);
        if (merchant == null) {
            throw new ServiceException("商家不存在");
        }

        // 1) 若要改手机号，做验证码 & 唯一性校验
        String newPhone = StringUtils.trimToNull(request.getContactPhone());
        String oldPhone = StringUtils.trimToNull(merchant.getContactPhone());
        boolean changePhone = newPhone != null && !newPhone.equals(oldPhone);

        if (changePhone) {
            // 1.1 验证码必填
            if (StringUtils.isEmpty(request.getSmsCode())) {
                throw new ServiceException("验证码不能为空");
            }
            validateSmsCodeWithRedisCache(newPhone, request.getSmsCode());

            // 1.2 唯一性校验（merchant 表）
            Merchant existPhone = merchantMapper.selectMerchantByPhone(newPhone);
            if (existPhone != null && !existPhone.getMerchantId().equals(merchantId)) {
                throw new ServiceException("该手机号已被其他商家使用");
            }
        }

        // 2) 更新 merchants 表（做“部分更新/仅更新非空”）
        Merchant toUpdate = new Merchant();
        toUpdate.setMerchantId(merchantId);
        toUpdate.setMerchantName(request.getMerchantName());
        toUpdate.setContactPerson(request.getContactPerson());
        toUpdate.setAvatarUrl(request.getAvatarUrl());
        toUpdate.setAddress(request.getAddress());
        toUpdate.setLatitude(request.getLatitude());
        toUpdate.setLongitude(request.getLongitude());
        if (changePhone) {
            toUpdate.setContactPhone(newPhone);
        }
        merchantMapper.updateSelective(toUpdate);

        // 3) 同步 sys_user（用户名与手机都用新号码，与你复用手机号登录逻辑对齐）
        if (changePhone) {
            SysUser sysUser = new SysUser();
            sysUser.setUserId(merchant.getUserId());
            sysUser.setUserName(newPhone);
            sysUser.setPhonenumber(newPhone);
            sysUserMapper.updateUser(sysUser);

            // 4) 处理登录态：强制重新登录 or 刷新
            // 推荐：强制下线当前账号，提示重新登录
            LoginUser loginUser = SecurityUtils.getLoginUser();
            if (loginUser != null) {
                tokenService.delLoginUser(loginUser.getToken()); // 使当前 Token 失效
            }
        }
    }
    private void validateSmsCodeWithRedisCache(String phone, String smsCode) {
        // 保护：剔除空白字符，避免复制粘贴带空格导致误判
        String inputCode = org.apache.commons.lang3.StringUtils.deleteWhitespace(smsCode);

        String cacheKey = SMS_CODE_KEY + phone;
        String cachedCode = redisCache.getCacheObject(cacheKey);

        if (StringUtils.isEmpty(cachedCode)) {
            throw new ServiceException("验证码已过期，请重新获取");
        }
        if (!cachedCode.equals(inputCode)) {
            throw new ServiceException("验证码错误");
        }

        // 验证通过，删除缓存中的验证码（一次性）
        redisCache.deleteObject(cacheKey);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateStatusResponse updateMerchantStatus(Long merchantId, Integer status) {
        // 1. 参数校验
        if (status == null || (status != 0 && status != 1)) {
            throw new ServiceException("状态参数错误，只能是0（营业）或1（休息）");
        }

        // 2. 查询商家信息
        Merchant merchant = merchantMapper.selectMerchantById(merchantId);
        if (merchant == null) {
            throw new ServiceException("商家信息不存在");
        }

        // 3. 检查是否被封禁
        if (merchant.getStatus() == 2) {
            throw new ServiceException("账号已被封禁，无法修改状态");
        }

        // 4. 检查审核状态（只有审核通过的商家才能修改状态）
        String auditStatus = StringUtils.defaultIfBlank(
                merchant.getExternField1(), "PENDING_INFO");

        if (!"APPROVED".equals(auditStatus)) {
            String message = getAuditStatusMessage(auditStatus);
            throw new ServiceException(message);
        }

        // 5. 检查信息完整性
        if (!isInfoComplete(merchant)) {
            throw new ServiceException("请先完善商家信息");
        }

        // 6. 更新状态
        Merchant updateMerchant = new Merchant();
        updateMerchant.setMerchantId(merchantId);
        updateMerchant.setStatus(status);

        int rows = merchantMapper.updateMerchant(updateMerchant);
        if (rows <= 0) {
            throw new ServiceException("状态更新失败");
        }

        // 7. 构建返回结果
        String statusText = getStatusText(status);

        return UpdateStatusResponse.builder()
                .status(status)
                .statusText(statusText)
                .build();
    }


    /**
     * 获取审核状态提示消息
     */
    private String getAuditStatusMessage(String auditStatus) {
        Map<String, String> messageMap = new HashMap<>();
        messageMap.put("PENDING_INFO", "请先完善商家信息并提交审核");
        messageMap.put("UNDER_REVIEW", "您的入驻申请正在审核中，请耐心等待");
        messageMap.put("REJECTED", "您的入驻申请已被拒绝，请修改后重新提交");
        return messageMap.getOrDefault(auditStatus, "只有审核通过的商家才能修改营业状态");
    }

    /**
     * 判断信息是否完善
     */
    private boolean isInfoComplete(Merchant merchant) {
        // 基本信息是否完善
        if ("待完善".equals(merchant.getMerchantName())) {
            return false;
        }
        if ("待完善".equals(merchant.getContactPerson())) {
            return false;
        }
        if ("待完善".equals(merchant.getAddress())) {
            return false;
        }

        // 证照是否完善
        if (merchant.getBusinessLicense() == null
                || merchant.getBusinessLicense().startsWith("待提交_")) {
            return false;
        }
        //后续再完善
//        if (merchant.getFoodLicense() == null
//                || merchant.getFoodLicense().startsWith("待提交_")) {
//            return false;
//        }

        return true;
    }

    /**
     * 判断是否可以营业
     */
    private boolean canOperate(Merchant merchant, String auditStatus) {
        // 必须审核通过
        if (!"APPROVED".equals(auditStatus)) {
            return false;
        }
        
        // 状态必须是营业中
        if (merchant.getStatus() != 0) {
            return false;
        }

        return true;
    }

    /**
     * 获取营业状态文本
     */
    private String getStatusText(Integer status) {
        Map<Integer, String> statusMap = new HashMap<>();
        statusMap.put(0, "营业中");
        statusMap.put(1, "休息中");
        statusMap.put(2, "已封禁");
        return statusMap.getOrDefault(status, "未知状态");
    }

    /**
     * 获取审核状态文本
     */
    private String getAuditStatusText(String auditStatus) {
        Map<String, String> auditStatusMap = new HashMap<>();
        auditStatusMap.put("PENDING_INFO", "待完善信息");
        auditStatusMap.put("UNDER_REVIEW", "审核中");
        auditStatusMap.put("APPROVED", "已通过");
        auditStatusMap.put("REJECTED", "已拒绝");
        return auditStatusMap.getOrDefault(auditStatus, "未知状态");
    }

    /**
     * 获取图片URL（这里可以扩展，如果需要从其他地方读取图片）
     * 建议在入驻时将图片URL存储在额外字段或关联表中
     */
    private String getImageUrl(Merchant merchant, String type) {
        // 示例：如果使用额外字段存储
        // 实际项目中建议创建 merchant_images 表存储各种图片
        
        // 临时方案：返回null，前端处理
        // 正式方案：从关联表或JSON字段中读取
        return null;
    }

    /**
     * 手机号脱敏
     */
    private String desensitizePhone(String phone) {
        if (StringUtils.isEmpty(phone) || phone.length() != 11) {
            return phone;
        }
        return phone.substring(0, 3) + "****" + phone.substring(7);
    }
}
